package com.cnap.multiclouldmgmt.service.impl;

import com.cnap.multiclouldmgmt.model.AccountInfo;
import com.cnap.multiclouldmgmt.model.RepByPage;
import com.cnap.multiclouldmgmt.model.network.InfoRepModel;
import com.cnap.multiclouldmgmt.model.network.LinkRepInfoModel;
import com.cnap.multiclouldmgmt.model.network.LinkResInfoModel;
import com.cnap.multiclouldmgmt.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.util.*;

@Service("NetworkInfoServiceImpl")
public class NetworkInfoServiceImpl implements NetworkInfoService {

    private final static Logger LOGGER = LoggerFactory.getLogger(NetworkInfoServiceImpl.class);

    @Value("${center.networkInfoUrl}")
    private  String networkInfoUrl;

    @Value("${center.networkInfoPath}")
    private  String networkInfoPath;

    private static RestTemplate restTemplate = null;

    @Autowired
    private CacheService cacheService;


    @Override
    public RepByPage<LinkResInfoModel> getLinkResInfo(int pageSize, int pageNo) {

        RepByPage<LinkResInfoModel> result = new RepByPage<>();
        result.setPageNo(pageNo);
        result.setPageSize(pageSize);
        result.setTotalNum(0);
        result.setResult(new ArrayList<>());

        String url = networkInfoUrl + networkInfoPath;

        if (restTemplate == null) {
            restTemplate = genRestTemplate();
        }
        //LOGGER.warn("getLinkResInfo getInfo url={}", url);
        try {
            ResponseEntity<InfoRepModel> responseEntity =
                    restTemplate.getForEntity(url, InfoRepModel.class);

            //LOGGER.warn("getLinkResInfo getInfo result={}", JSON.toJSONString(responseEntity));

            if (responseEntity.getStatusCode().is2xxSuccessful()){

                if ((responseEntity.getBody() != null)
                        &&(responseEntity.getBody().getResult() != null)
                        &&(!responseEntity.getBody().getResult().isEmpty())){

                    result.setTotalNum(responseEntity.getBody().getResult().size());

                    int beginIndex = (pageNo - 1) * pageSize;

                    if (beginIndex > result.getTotalNum()){
                        return result;
                    }

                    int endIndex = Math.min((pageNo * pageSize), result.getTotalNum());

                    for (int i = beginIndex;i < endIndex;i++){
                        result.getResult().add(transLinkRep(responseEntity.getBody().getResult().get(i)));
                    }
                }
            }

        }catch (Exception e){
            LOGGER.error("getLinkResInfo getInfo failed url={}", url,e);

        }


        return result;
    }

    private LinkResInfoModel transLinkRep(LinkRepInfoModel linkRepInfoModel) {

        LinkResInfoModel linkResInfoModel = new LinkResInfoModel();
        linkResInfoModel.setLinkName(linkRepInfoModel.getName());
        //linkName增加从到谁
        if ((linkRepInfoModel.getPrimaryDevices() != null)&&(!linkRepInfoModel.getPrimaryDevices().isEmpty())){
            int size = linkRepInfoModel.getPrimaryDevices().size();
            StringBuilder deviceStr = new StringBuilder();
            deviceStr.append("(");
            for(int i = 0;i < size;i++){
                deviceStr.append(linkRepInfoModel.getPrimaryDevices().get(i));
                if (i < (size - 1)){
                    deviceStr.append("->");
                }
            }
            deviceStr.append(")");
            linkResInfoModel.setLinkName(linkResInfoModel.getLinkName() + deviceStr.toString());
        }
        //vpnnames作为虚网名称，如果不是我们创建的，就没有vpn，那就不保存
        if((linkRepInfoModel.getVpnNames() != null)&&(!linkRepInfoModel.getVpnNames().isEmpty())) {
            linkResInfoModel.setvNetName(linkRepInfoModel.getVpnNames().get(0));
        }else{
            linkResInfoModel.setvNetName("");
        }
        linkResInfoModel.setBandwidthMbps((int)(linkRepInfoModel.getBw()/1000/1000));

        //判断网络延时是不是数字
        if (NumberUtils.isParsable(linkRepInfoModel.getDelay())) {
            //网络时延
            linkResInfoModel.setDelayMs(Double.parseDouble(
                    String.format("%.2f", NumberUtils.toFloat(linkRepInfoModel.getDelay()))));
        }
        //抖动
        if (NumberUtils.isParsable(linkRepInfoModel.getJitter())) {
            linkResInfoModel.setNetJitterMs(
                    Double.parseDouble(
                            String.format("%.2f", Double.parseDouble(linkRepInfoModel.getJitter()))));
        }
        //丢包率
        if (NumberUtils.isParsable(linkRepInfoModel.getLoss())) {
            linkResInfoModel.setLossRate(Double.parseDouble(
                    String.format("%.2f", NumberUtils.toFloat(linkRepInfoModel.getLoss()))));
        }
        //平均流量
        linkResInfoModel.setAvgFlow5MinKbps(((int)linkRepInfoModel.getRate())/1024);
        //状态
        if (StringUtils.equalsIgnoreCase(linkRepInfoModel.getStatus(),"up")){
            linkResInfoModel.setStatus("正常");
        }else{
            linkResInfoModel.setStatus("断开");
        }

        AccountInfo accountInfo =  cacheService.getAccountNameByNetName(linkResInfoModel.getvNetName());
        if (accountInfo != null) {
            linkResInfoModel.setAccountName(accountInfo.getAccountName());
            linkResInfoModel.setCloudType(accountInfo.getCloudType());
        }

        linkResInfoModel.setRecordDate(new Date());
        return linkResInfoModel;
    }

    private RestTemplate genRestTemplate(){
        try {
            TrustStrategy acceptingTrustStrategy = (chain, authType) -> true;
            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);

            HttpClientBuilder clientBuilder = HttpClients.custom();

            CloseableHttpClient httpClient = clientBuilder.setSSLSocketFactory(sslsf).build();

            HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
            httpRequestFactory.setConnectionRequestTimeout(30000);
            httpRequestFactory.setConnectTimeout(30000);
            httpRequestFactory.setReadTimeout(30000);

            httpRequestFactory.setHttpClient(httpClient);

            return new RestTemplate(httpRequestFactory);
        }catch (Exception e){
            LOGGER.error("genRestTemplate failed ",e);
        }

        return new RestTemplate();
    }
}
